package com.suxin.spring.linked;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author Tang
 * @classname FilterChainProxy
 * @description [  ]
 * @date 2022/8/29 10:49
 */
public class FilterChainProxy implements Filter{

    private List<SecurityFilterChain> securityFilterChains;

    public FilterChainProxy(List<SecurityFilterChain> securityFilterChains) {
        this.securityFilterChains = securityFilterChains;
    }

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response,
                         FilterChain filterChain) {
        // filterChain 是原生的servlet filterChain
        // 获取匹配的 filters
        List<Filter> filters = getFilters(request);
        new VirtualFilter(filters,request,filterChain)
                .doFilter(request, response);
    }


    public static class VirtualFilter implements FilterChain {

        private List<Filter> securityFilters;
        private FilterChain outFilterChain;
        private HttpServletRequest request;
        private int size;
        private int currentPosition;

        public VirtualFilter(List<Filter> securityFilters,HttpServletRequest request,FilterChain outFilterChain) {
            this.securityFilters = securityFilters;
            this.request = request;
            this.currentPosition = 0;
            this.size = this.securityFilters.size();
            this.outFilterChain = outFilterChain;
        }

        @Override
        public void doFilter(HttpServletRequest request, HttpServletResponse response) {
            if (size == currentPosition) {
                // 执行原生的chain
                outFilterChain.doFilter(request,response);
            }else {
                Filter filter = this.securityFilters.get(this.currentPosition++);
                filter.doFilter(request,response,this);
            }
        }

    }

    /**
     * getFilters
     * @param request
     * @return
     */
    private List<Filter> getFilters(HttpServletRequest request) {
        for (SecurityFilterChain chain : getSecurityFilterChain()) {
            if (chain.matches(request)) {
                return chain.getFilters();
            }
        }
        return null;
    }



    public List<SecurityFilterChain> getSecurityFilterChain() {
        return securityFilterChains;
    }
}
